package ctn.service.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import ctn.contant.PlugContant;
import ctn.convert.CPAInfoCovert;
import ctn.convert.CPAVerCovert;
import ctn.dao.hibernate.impl.SpecDaoImpl;
import ctn.dao.inteface.CPAInfoDao;
import ctn.dao.inteface.CPAVerDao;
import ctn.dao.inteface.CTNUserDao;
import ctn.dao.inteface.LinkEventDao;
import ctn.event.CTNEvent;
import ctn.event.CTNEventAddPJ;
import ctn.event.CTNEventDelete;
import ctn.event.CTNEventResetPWD;
import ctn.event.processor.EventProcessor;
import ctn.hibernate.po.CtnCpaInfo;
import ctn.hibernate.po.CtnCpaSpec;
import ctn.hibernate.po.CtnCpaVer;
import ctn.hibernate.po.CtnGrp;
import ctn.hibernate.po.CtnLinkApprove;
import ctn.hibernate.po.CtnLinkEvent;
import ctn.hibernate.po.CtnUser;
import ctn.hibernate.po.CtnUserMsgParm;
import ctn.service.dto.MyProjectDTO;
import ctn.service.dto.PlugDTO;
import ctn.service.inteface.PlugService;
import ctn.util.CPAUtil;
import ctn.util.CTNUserUtil;
import ctn.util.EventUtil;
import ctn.util.StringUtils;
import ctn.util.jmesa.DateUtils;
import ctn.util.jmesa.PaginationCriteria;
@Service
@Transactional
public class PlugServiceImpl implements PlugService {
	@Autowired
	private CPAInfoDao cPAInfoDaoImpl;
	@Autowired
	private CPAVerDao cPAVerDaoImpl;
	@Autowired
	private CTNUserDao cTNUserDaoImpl;
	@Autowired
	private LinkEventDao linkEventDaoImpl;
	@Autowired
	private SpecDaoImpl specDaoImpl;
	@Autowired
	private EventUtil util;
	@Autowired
	private CPAUtil cpaUtil;
	@Autowired
	@Qualifier("filePro")
	private Properties filePro;
	@Override
	public Long getWplugListCount(PaginationCriteria criteria) {
		return cPAInfoDaoImpl.getplugListCountByCriteria(criteria);
	}

	@Override
	public List<PlugDTO> getWplugList(PaginationCriteria criteria) {
		return cPAInfoDaoImpl.getWplugListByCriteria(criteria);
	}

	@Override
	public void savePlug(PlugDTO plugDTO,CommonsMultipartFile uf) {
		CtnCpaInfo cpainfo=new CtnCpaInfo();
		cpainfo=CPAInfoCovert.convertDTO2Po(plugDTO, cpainfo);
		cPAInfoDaoImpl.createPlug(cpainfo);
		CtnCpaVer cpaVer= new CtnCpaVer();
		cpaVer= CPAVerCovert.convertPo2VER(plugDTO,cpainfo,cpaVer);
		cPAVerDaoImpl.createVer(cpaVer);
		CtnCpaSpec spec=new CtnCpaSpec();
		spec.setSpecTyp(PlugContant.SPEC_TYPE_REQUIREMENT);
		spec.setCreateDate(new Date());
		spec.setCtnCpaVer(cpaVer);
		spec.setCtnUser(CTNUserUtil.getUser());
		spec.setFileName(uf.getOriginalFilename());
		specDaoImpl.saveCpaSpec(spec);
		CTNEventAddPJ addpj=new CTNEventAddPJ(String.valueOf(cpaVer.getId()));
		List<CtnUser> list=cTNUserDaoImpl.getGrpUsers(1L);
		CtnLinkEvent event= cpaUtil.genEvent(addpj);
    	for(CtnUser toUser:list){
    		String link=cpaUtil.genLink(String.valueOf(toUser.getId()), event);
    		Set<CtnUserMsgParm> parms=new HashSet<CtnUserMsgParm>();
        	parms.add(new CtnUserMsgParm("LN",link));
        	parms.add(new CtnUserMsgParm("UR",CTNUserUtil.getUser().getName()));
        	parms.add(new CtnUserMsgParm("DT",DateUtils.formatDateTime("yyyy-MM-dd HH:mm:ss", new Date())));
        	parms.add(new CtnUserMsgParm("TL",cpainfo.getName()));
    		cpaUtil.genMsg( 3L,toUser.getId(), parms);
    	}
		String filepath=cpaUtil.getSpecFilePath(spec);
		String folderPath=filepath.replace(uf.getOriginalFilename(), "");
		File folder=new File(folderPath);
		File file=new File(filepath);
		if(!folder.exists()){
			folder.mkdirs();
		}
		BufferedOutputStream os = null;
		BufferedInputStream is = null;
		try {
			os = new BufferedOutputStream(new FileOutputStream(file));
			is = new BufferedInputStream(uf.getInputStream());

			byte[] byteA;
			int read = 0;
			while (read != -1) {
				byteA = new byte[1024];
				read = is.read(byteA);
				if (read != -1) {
					os.write(byteA, 0, read);
				}
			}
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (os != null) {
				try {
					os.close();
				} catch (Exception ex) {
				}
			}
		}
	}

	
	@Override
	public PlugDTO getWplug(Long id) {
		
		PlugDTO plugDTO=cPAInfoDaoImpl.getWplug(id);
		
		if(plugDTO.getCreateUserName().equals(CTNUserUtil.getUser().getName())){
			plugDTO.setEdit(true);
      	};
      	List<CtnGrp> grps=cPAInfoDaoImpl.getAllGrps();
      	plugDTO.setGrps(grps);
		return plugDTO;
	}

	@Override
	public void delPlug(Long id) {
		PlugDTO plugDTO=cPAInfoDaoImpl.getWplug(id);
		cPAInfoDaoImpl.updateCpaVerStatus(String.valueOf(plugDTO.getVerID()),PlugContant.STATUS_WAIT_CLOSE);
		//cPAInfoDaoImpl.delPlug(id);
		CTNEventDelete delEvent=new CTNEventDelete(String.valueOf(plugDTO.getVerID()),"");
		
    	List<CtnUser> list=cTNUserDaoImpl.getGrpUsers(1L);
    	CtnLinkEvent event= cpaUtil.genEvent(delEvent);
    	for(CtnUser toUser:list){
    		String link=cpaUtil.genLink(String.valueOf(toUser.getId()), event);
    		Set<CtnUserMsgParm> parms=new HashSet<CtnUserMsgParm>();
        	parms.add(new CtnUserMsgParm("LN",link));
        	parms.add(new CtnUserMsgParm("UR",CTNUserUtil.getUser().getName()));
        	parms.add(new CtnUserMsgParm("DT",DateUtils.formatDateTime("yyyy-MM-dd HH:mm:ss", new Date())));
        	parms.add(new CtnUserMsgParm("TL",plugDTO.getCpaName()));
    		cpaUtil.genMsg( 1L,toUser.getId(), parms);
    	}
	/*	CtnUserMsg ctnUserMsg= new   CtnUserMsg(null, CTNUserUtil.getUser(), CtnMsgTempl ctnMsgTempl,
				Long sendUserId, Date sendDate, String status);
		MsgUtil msgUtil= new MsgUtil();
		msgUtil.equals()*/
	}

	

	@Override
	public void editPlug(PlugDTO plugDTO) {
		CtnCpaInfo cpainfo=new CtnCpaInfo();
		cpainfo.setStatus(plugDTO.getVerStatus());
		cpainfo=CPAInfoCovert.convertDTO2Po(plugDTO, cpainfo);
		CtnCpaVer cpaVer= new CtnCpaVer();
		cpaVer= CPAVerCovert.convertPo2VER(plugDTO,cpainfo,cpaVer);
		cPAInfoDaoImpl.editPlug(cpainfo);
		List<CtnUser> list=cTNUserDaoImpl.getGrpUsers(Long.parseLong(plugDTO.getImplGrpIDStr()));
		List<CtnUser> list2=cTNUserDaoImpl.getGrpUsers(Long.parseLong(plugDTO.getWatchGrpIDStr()));
		for(CtnUser user1:list){
			if(!list2.isEmpty()){
				if(list2.contains(user1)){
					list2.remove(user1);
				}
			}
		}
		Set<CtnUserMsgParm> parms=new HashSet<CtnUserMsgParm>();
    	parms.add(new CtnUserMsgParm("DT",DateUtils.formatDateTime("yyyy-MM-dd HH:mm:ss", new Date())));
    	parms.add(new CtnUserMsgParm("TL",cpainfo.getName()));
    	for(CtnUser toUser:list){
    		cpaUtil.genMsg( 2L,toUser.getId(), parms);
    	}
    	for(CtnUser toUser:list2){
    		cpaUtil.genMsg( 2L,toUser.getId(), parms);
    	}
		if(cpaVer.getId()!=null){
			cPAVerDaoImpl.editVer(cpaVer);
			
		}else{
			cPAVerDaoImpl.createVer(cpaVer);
			plugDTO.setVerID(cpaVer.getId());
		}
		if (plugDTO.getUpFile()!= null) {
			CommonsMultipartFile uf = plugDTO.getUpFile();
			CtnCpaSpec spec=new CtnCpaSpec();
			spec.setSpecTyp(PlugContant.SPEC_TYPE_REQUIREMENT);
			spec.setCreateDate(new Date());
			spec.setCtnCpaVer(cpaVer);
			spec.setCtnUser(CTNUserUtil.getUser());
			spec.setFileName(uf.getOriginalFilename());
			specDaoImpl.saveCpaSpec(spec);
			
	    	String filepath=cpaUtil.getSpecFilePath(spec);
			String folderPath=filepath.replace(uf.getOriginalFilename(), "");
			File folder=new File(folderPath);
			File file=new File(filepath);
			if(!folder.exists()){
				folder.mkdirs();
			}
			BufferedOutputStream os = null;
			BufferedInputStream is = null;
			try {
				os = new BufferedOutputStream(new FileOutputStream(file));
				is = new BufferedInputStream(uf.getInputStream());

				byte[] byteA;
				int read = 0;
				while (read != -1) {
					byteA = new byte[1024];
					read = is.read(byteA);
					if (read != -1) {
						os.write(byteA, 0, read);
					}
				}
				os.flush();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (os != null) {
					try {
						os.close();
					} catch (Exception ex) {
					}
				}
			}
		}
	}

	@Override
	public List<CtnUser> getDoPlugGrpUsers(Long implGrpID) {
		Set<CtnUser> set=cTNUserDaoImpl.getUserByGrpID(implGrpID);
		List<CtnUser> list=new ArrayList<CtnUser>();

		if(set!=null&&set.size()!=0)
			list.addAll(set);
		return list;
	}
	@Override
	public boolean processLink(String uUID, String userID) {
		CtnLinkApprove cla=linkEventDaoImpl.getCtnLinkApproveByID(uUID);
		if(cla==null){
			return false;
		}
		Date upDate=cla.getUpdateDate();
		String linkkeepStr=filePro.getProperty(PlugContant.LINK_KEEP_EFFECTIVE);
		long timeKeep=new Date().getTime()-upDate.getTime();
		long linkkeep=86400000;
		if(!StringUtils.isEmptyString(linkkeepStr)){
			linkkeep=Long.parseLong(linkkeepStr);
		}
		if(timeKeep>linkkeep){
			return false;
		}
		cla.setStatus(PlugContant.Link_APPROVE_STATUS_DONE);
		linkEventDaoImpl.updateLinkApprove(cla);
		return true;
	}

	@Override
	public boolean processEvent(String uUID) {
		CtnLinkApprove cla=linkEventDaoImpl.getCtnLinkApproveByID(uUID);
		int count=linkEventDaoImpl.getNoAcceptLinkCount(cla);
		if(count==0){
			CtnLinkEvent event=cla.getCtnLinkEvent();			
			String className=PlugContant.eventMap.get(event.getEventVal());
			try {
				CTNEvent e=(CTNEvent) Class.forName(className).newInstance();
				e.setPropValue(event.getEventLink());
				EventProcessor ep=util.getFactory(e.getEventID()).getEventProcessor();
				ep.process(e);
				if(e instanceof CTNEventResetPWD)
					return false;
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return true;
		
		
	}

	@Override
	public void doTransferFun(MyProjectDTO myProjectDTO) {
		cPAInfoDaoImpl.updateCPAFunStatus(myProjectDTO.getFunID(),PlugContant.FUN_STATUS_WAIT_FOR_TRAN);
		
	}

	@Override
	public List<MyProjectDTO> getListMyProject(PaginationCriteria criteria) {
		
		return cPAInfoDaoImpl.getListMyProject(criteria);
	}

	@Override
	public Long getListMyProjectCount(PaginationCriteria criteria) {
		// TODO Auto-generated method stub
		return cPAInfoDaoImpl.getListMyProjectCount(criteria);
	}

	@Override
	public List<MyProjectDTO> getListMyCreateProject(PaginationCriteria criteria) {
		// TODO Auto-generated method stub
		return cPAInfoDaoImpl.getListMyCreateProject(criteria);
	}

	@Override
	public Long getListMyCreateProjectCount(PaginationCriteria criteria) {
		// TODO Auto-generated method stub
		return cPAInfoDaoImpl.getListMyCreateProjectCount(criteria);
	}

	@Override
	public Long getCreateProjUserIDbyFunID(String funID,Set<CtnUserMsgParm> parms) {
		// TODO Auto-generated method stub
		return cPAInfoDaoImpl.getCreateProjUserIDbyFunID(funID,parms);
	}

	@Override
	public void doDropFun(String funID) {
		cPAInfoDaoImpl.updateCPAFunStatus(funID,PlugContant.FUN_STATUS_WAIT_FOR_DROP);
	}

	@Override
	public void doCheckFun(String funID) {
		cPAInfoDaoImpl.updateCPAFunStatus(funID,PlugContant.FUN_STATUS_WAIT_FOR_COMP);
	}
	@Override
	public void doTransCpaVer(String id) {
		cPAInfoDaoImpl.updateCpaVerStatus(id,"WT");
		}
}
